#ifndef OSTRING_H
#define OSTRING_H

#include <string>
#include <vector>
#include <stack>
#include <iostream>
#include <sstream>
#include <map>

#include "Vertex.h"

namespace Y{

class OString{
	
	public:
		
		std::string str;
		static int	OS;
	
	public:
		
		OString();
		OString( char c );
		OString( const char *c );
		OString( const std::string& s );
		~OString();
		operator std::string& () { return str; }
		operator const std::string& () const { return str; }
		const std::string& std_string () const { return str; }
		std::string& std_string () { return str; }
		operator const char * () const { return str.c_str(); }
		const char * data () const { return str.c_str(); }
		
		void toOSPath();
		
		int	hash() const;
		
		int		to_i() const{ int i;	std::istringstream stream(str); stream >> i; return i; }
		float	to_f() const{ float i;  std::istringstream stream(str); stream >> i; return i; }
		bool	to_b() const{ bool i;	std::istringstream stream(str); stream >> i; return i; }
		
		char at (int i) const { return str.at(i); }
		char operator() (int i) const { return str.at(i); }
		char operator[] (int i) const { return str.at(i); }
		char& at (int i) { return str.at(i); }
		char& operator() (int i) { return str.at(i); }
		char& operator[] (int i) { return str.at(i); }
		
		bool contains (const char *c){return (str.find(c) != std::string::npos);}
		bool empty (){ return (str.empty()); }
		
		bool operator== (const char *c){ return (str == c); }
		bool operator!= (const char *c){ return (str != c); }
		bool operator< (const OString& s) const{ return (s.str < str); }
		bool operator> (const OString& s) const{ return (s.str > str); }
		bool operator== (const OString& s)const{ return (s.str == str); }
		bool operator== (char c)const{ return (str.at(0) == c); }
		
		OString operator+ (const char *c){ OString r = str; r.append(c); return r; }
		OString operator+ (float f)		{ OString r = str; std::ostringstream tmp; tmp << f; r.append( tmp.str() );return r; }
		OString operator+ (int f)		{ OString r = str; std::ostringstream tmp; tmp << f; r.append( tmp.str() );return r; }
		OString operator+ (bool f)		{ OString r = str; std::ostringstream tmp; tmp << f; r.append( tmp.str() );return r; }
		OString& operator+= (const char *c)		{ str.append(c);return *this; }
		OString& operator+= (int i)		{ std::ostringstream tmp; tmp << i; str.append( tmp.str() );return *this; }
		OString& operator+= (float f)	{ std::ostringstream tmp; tmp << f; str.append( tmp.str() );return *this; }
		OString& operator+= (bool b)	{ if(b)str.append("true");else str.append("false");return *this;  }
		
		
		bool lenientEquals (const char *c) const;
		
		OString& append ( const std::string& s );
		OString& append ( const char *c );
		OString& append ( const OString& os );
		OString& append ( int i );
		
		OString cullBackFrom ( const char *c, int length = -1, int searchStart = 0 );
		OString cullOnFrom ( const char *c, int length = -1, int searchStart = 0 );
		
		OString rcullBackFrom ( const char *c, int length = -1, int searchStart = -1 );
		OString rcullOnFrom ( const char *c, int length = -1, int searchStart = -1 );
		
		OString cullAfter ( const char *c, int length = -1, int searchStart = 0 );
		OString cullBefore ( const char *c, int length = -1, int searchStart = 0 );
		
		OString rcullAfter ( const char *c, int length = -1, int searchStart = -1 );
		OString rcullBefore ( const char *c, int length = -1, int searchStart = -1 );
		
		OString& remove ( int p0, int p1 );
		OString& remove_c ( int p0, char c );
		OString& chop ( int n );
		
		OString& trim ();
		
		OString& to_lower ();
		OString& to_upper ();
		OString to_lower_cpy () const;
		OString to_upper_cpy () const;
		
		OString& replace ( int p0, int p1, const char *c );
		OString& replace ( const char *s0, const char *s1 );
		OString& replace_all_with ( const char *tokens, char replacer );
		
		OString substring ( int p0, int p1 = -1 );
		OString substring_l ( int p0, int l = -1 );
		OString substring_c ( int p0, char c );
		OString substring_bc ( int p0, char c );
		
		int find ( const char *c, int p0 = 0 );
		int rfind ( const char *c, int p0 = -1 );
		int find_first_of ( const char *c, int p0 = 0 );
		
		int size() const;
		int length() const;
};

class OPString: public OString{
	
	public:
		std::vector < Pair2i > delimiterPositions;
		std::vector < OString > delimiters;
		int placemark;
		int delimiterIndex;
		int numberOfSections;
		
		bool delimitersAsSections;
		bool oddEven;
		
	public:
		
		OPString();
		OPString( const char *c );
		OPString( const std::string& s );
		OPString( const OString& os );
		OPString& operator= ( const OString& os );
		OPString& operator= ( const char *c );
		
		void setDelimiters ( const char *c );
		void addDelimiters ( const char *c );
		void addStringDelimiter ( const char *c );
		void clearDelimiters ();
		void parse (bool das = false);
		
		OString nextSection (bool includeDelim = false);
		void skipSection ();
		int numSections () { return numberOfSections; }
		OString& whatDelimiterAtIndex (int di);
		OString& nextDelimiter ();
		OString& lastDelimiter ();
		bool hasMoreSections (){ return (delimiterIndex < numberOfSections); }
		
		void chunkify( const char *c, std::vector< OString >& );
};



struct ostrcmp
{
	bool operator()(const OString& s0, const OString& s1) const
	{
		return (s0 < s1);
	}
};

}
/*
"0123456789012345678901"
"This is a test  string"
delimiter ' '
delimiterPositions < 4,7,9,14,15 >
placemark:0
delimIndex:0
substring(0,3);
placemark:5
delimIndex:1
substring(5,6);
placemark:8
delimIndex:2
substring(8,8);
placemark:10
delimIndex:3
substring(10,13);
placemark:15
delimIndex:4
substring(15,14);
*/
#endif